using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace Code_Generator
{
	public class ProcBuilder : Builder
	{
		public ProcBuilder() { }

		public ProcBuilder(Setup setup) : base(setup) { }


		public void CreateSelectAllTokensProc()
		{
			Setup.PopulateMetaData();
			var template = LoadTemplate("Procs", "SelectAllTokens");

			template.Replace("$SelectList$", Columns(MetaData.Columns.Where(c => c.IsPrimaryKey || c.IsTokenColumn)));

			var targetFilePath = Path.Combine(Setup.TargetFolder, Setup.ClassName + "SelectAllTokens.proc.sql");
			File.WriteAllText(targetFilePath, template.ToString());
		}

		public void CreateSelectModelProc()
		{
			CreateSelectModelProc(Setup.TableName + "SelectModel", MetaData.PrimaryColumns);
		}

		//public void CreateSelectModelByParentProc()
		//{
		//	var procName = Setup.TableName + "SelectModelBy" + MetaData.ParentColumn.SqlName;
		//	CreateSelectModelProc(procName, new DBColumn[] { MetaData.ParentColumn });
		//}

		//public void CreateSelectModelProc(string procName, params DBColumn[] keyColumns)
		//{
		//	CreateSelectModelProc(procName, keyColumns.AsEnumerable());
		//}

		public void CreateSelectModelProc(string procName, IEnumerable<DBColumn> keyColumns)
		{
			Setup.PopulateMetaData();
			var template = LoadTemplate("Procs", "SelectModel");

			template.Replace("$ProcName$", procName);
			template.Replace("$Parameters$", Parameters(keyColumns));
			template.Replace("$SelectList$", Columns(MetaData.Columns));
			template.Replace("$WhereList$", AndWhere(keyColumns));

			var targetFilePath = Path.Combine(Setup.TargetFolder, procName + ".proc.sql");
			File.WriteAllText(targetFilePath, template.ToString());
		}

		public void CreateInsertModelProc()
		{
			Setup.PopulateMetaData();
			var template = LoadTemplate("Procs", "InsertModel");

			template.Replace("$Parameters$", Parameters(MetaData.Columns.Where(c => !c.IsAuditField)));

			var columnText = new List<string>();
			var valueText = new List<string>();
			foreach (var column in MetaData.Columns.Where(c => !c.IsIdentity))
			{
				columnText.Add("\t\t" + column.SqlName);
				if (column.IsCreatedDate || column.IsUpdatedDate)
					valueText.Add("\t\tGetDate()");
				else if (column.IsCreatedBy || column.IsUpdatedBy)
					valueText.Add("\t\t@Audit_UserKey");
				else
					valueText.Add("\t\t@" + column.SqlName);
			}
			template.Replace("$ColumnList$", string.Join(",\r\n", columnText));
			template.Replace("$ValueList$", string.Join(",\r\n", valueText));




			var targetFilePath = Path.Combine(Setup.TargetFolder, Setup.ClassName + "InsertModel.proc.sql");
			File.WriteAllText(targetFilePath, template.ToString());
		}

		public void CreateDeleteProc()
		{
			Setup.PopulateMetaData();
			var template = LoadTemplate("Procs", "Delete");

			var targetFilePath = Path.Combine(Setup.TargetFolder, Setup.ClassName + "Delete.proc.sql");
			File.WriteAllText(targetFilePath, template.ToString());
		}

		public void CreateUpdateModelProc()
		{
			Setup.PopulateMetaData();
			var template = LoadTemplate("Procs", "UpdateModel");


			template.Replace("$Parameters$", Parameters(MetaData.Columns.Where(c => !c.IsAuditField)));

			var updateText = new List<string>();
			foreach (var column in MetaData.Columns.Where(c => !c.IsIdentity && !c.IsCreatedBy && !c.IsCreatedDate))
			{
				if (column.IsUpdatedDate)
					updateText.Add("\t\t" + column.SqlName + " = GetDate()");
				else if (column.IsUpdatedBy)
					updateText.Add("\t\t" + column.SqlName + " = @Audit_UserKey");
				else
					updateText.Add("\t\t" + column.SqlName + " = @" + column.SqlName);
			}
			template.Replace("$UpdateList$", string.Join(",\r\n", updateText));


			var targetFilePath = Path.Combine(Setup.TargetFolder, Setup.ClassName + "UpdateModel.proc.sql");
			File.WriteAllText(targetFilePath, template.ToString());
		}

		protected override StringBuilder LoadTemplate(string section, string file)
		{
			var template = base.LoadTemplate(section, file);

			template.Replace("$SchemaName$", Setup.SchemaName);
			template.Replace("$TableName$", Setup.TableName);

			template.Replace("$PrimaryKey-Parameter$", Parameters(MetaData.PrimaryColumns));
			template.Replace("$PrimaryKey-ParameterName$", MetaData.PrimaryColumn.SqlParameterName);
			template.Replace("$PrimaryKey-Where$", AndWhere(MetaData.PrimaryColumns));



			return template;
		}

		private static string Parameters(IEnumerable<DBColumn> columns)
		{
			var parameterText = new List<string>();
			foreach (var column in columns)
			{
				parameterText.Add("\t@" + column.SqlName + " " + column.FullSqlType);
			}
			return string.Join(",\r\n", parameterText);
		}

		private static string Columns(IEnumerable<DBColumn> columns)
		{
			var columnText = new List<string>();
			foreach (var column in columns)
			{
				columnText.Add("\t\t" + column.SqlName);
			}
			return string.Join(",\r\n", columnText);
		}

		private static string Values(IEnumerable<DBColumn> columns)
		{
			var valueText = new List<string>();
			foreach (var column in columns)
			{
				valueText.Add("\t\t@" + column.SqlName);
			}
			return string.Join(",\r\n", valueText);
		}

		private static string Updates(IEnumerable<DBColumn> columns)
		{
			var parameters = new List<string>();
			foreach (var column in columns)
			{
				parameters.Add("\t\t" + column.SqlName + " = @" + column.SqlName);
			}
			return string.Join(",\r\n", parameters);
		}

		private static string AndWhere(IEnumerable<DBColumn> columns)
		{
			var parameters = new List<string>();
			foreach (var column in columns)
			{
				var param = column.SqlName + " = " + "@" + column.SqlName;
				parameters.Add(param);
			}
			return string.Join(" AND ", parameters);
		}


	}
}

